package com.kinyx.framework.bean;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

import com.kinyx.framework.annotation.assist.Tester;
import com.kinyx.framework.utils.KArrayUtils;
import com.kinyx.framework.utils.KListUtils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
 * 字符串格式化对象
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Tester("com.kinyx.framework.bean.StringFormatter_Tester")
public final class StringFormatter {

	public static enum Type {
		/** 无参数拼接格式 */
		NoArg,
		/** 忽略该格式与参数 */
		Ignore;
	}

	/** 格式 */
	private final StringBuilder format = new StringBuilder();
	/** 参数 */
	private final List<Object> args = new ArrayList<>();

	/**
	 * 构造方法
	 * @return 新对象
	 */
	public static StringFormatter of() { return new StringFormatter(); }

	/**
	 * 追加格式
	 * @param format 格式
	 * @return 本对象
	 */
	public StringFormatter s(final String format) {
		this.format.append(format);
		return this;
	}

	/**
	 * 追加参数
	 * @param arg 参数
	 * @return 本对象
	 */
	public StringFormatter p(final Object arg) {
		this.args.add(arg);
		return this;
	}

	/**
	 * 追加格式和参数
	 * @param format 格式
	 * @param arg 参数
	 * @param args 参数
	 * @return 本对象
	 */
	public StringFormatter x(final String format, final Object arg, final Object... args) {
		this.s(format).p(arg);
		if (!KArrayUtils.isEmpty(args)) {
			for (final Object a : args) {
				this.p(a);
			}
		}
		return this;
	}

	/**
	 * 追加格式和参数
	 * @param format 格式
	 * @param supplier 参数生成器。返回Type.Ignore时，不拼接格式；返回Type.NoArg时，只拼接格式，不追加参数；返回其它值时正常追加格式及参数；
	 * @return 本对象
	 */
	public StringFormatter x(final String format, final Supplier<Object> supplier) {
		final Object arg = supplier.get();
		if (Type.Ignore.equals(arg)) {// 忽略该格式
		} else if (Type.NoArg.equals(arg)) {// 无参数拼接格式
			this.s(format);
		} else {// 拼接格式与参数
			this.x(format, arg);
		}
		return this;
	}

	/**
	 * 追加格式和参数
	 * @param format 格式
	 * @param checker 验证器。true：验证通过时追加参数；false：验证不通过时不追加参数；
	 * @param arg 参数
	 * @param args 参数
	 * @return 本对象
	 */
	public StringFormatter x(final String format, final Supplier<Boolean> checker, final Object arg, final Object... args) {
		if (Boolean.TRUE.equals(checker.get())) {
			this.x(format, arg);
			if (!KArrayUtils.isEmpty(args)) {
				for (final Object a : args) {
					this.p(a);
				}
			}
		}
		return this;
	}

	/**
	 * 追加格式和参数
	 * @param format 格式
	 * @param checker 验证器。true：验证通过时追加参数；false：验证不通过时不追加参数；
	 * @param supplier 参数生成器。验证器验证通过时，不特殊处理，直接追加参数。
	 * @param suppliers 参数生成器。验证器验证通过时，不特殊处理，直接追加参数。
	 * @return 本对象
	 */
	@SafeVarargs
	public final StringFormatter x(final String format, final Supplier<Boolean> checker, final Supplier<Object> supplier, final Supplier<Object>... suppliers) {
		if (Boolean.TRUE.equals(checker.get())) {
			this.x(format, supplier.get());
			if (!KArrayUtils.isEmpty(suppliers)) {
				for (final Supplier<Object> s : suppliers) {
					this.p(s.get());
				}
			}
		}
		return this;
	}

	/**
	 * 格式化
	 * @return 格式化结果
	 */
	public String format() {
		return this.args.isEmpty() ? this.format.toString() : String.format(this.format.toString(), KListUtils.toArray(this.args));
	}

}
